library(Seurat)
library(SeuratDisk)
library(reticulate)
library(scrubletR)
library(ggplot2)
library(patchwork)
library(dplyr)
library(data.table)
library(clustree)
library(reshape2)
library(tidyr)
library(gridExtra)
library(stringr)
library(plyr)
source("C:/Ryan/GitHub/trachtenberg-lab/transcriptomics/tools/seurat_functions.R")
source("C:/Ryan/GitHub/trachtenberg-lab/transcriptomics/tools/seurat_integration_functions.R")
source("C:/Ryan/GitHub/trachtenberg-lab/transcriptomics/xgboost/xgboost_train.R")
source("C:/Ryan/GitHub/trachtenberg-lab/transcriptomics/xgboost/plottingFxns.R")

classes <- c("Glutamatergic", "GABAergic", "Nonneuronal")
objs.mouse <- c()
objs.opossum <- c()
objs.i.mouse <- c()
objs.i.opossum <- c()
objs.m.mouse <- c()
objs.m.opossum <- c()

for (cl in classes) {

  obj.opossum <- readRDS(paste0("E:/Transcriptomics_V1/Opossum/seurat/opossum_v1_", tolower(cl), "_processed.rds"))
  obj.opossum$species <- "Opossum"
  obj.mouse.P38 <- readRDS(paste0("E:/Transcriptomics_V1/Mouse/seurat/mouse_v1_P38_", tolower(cl), "_processed.rds"))
  obj.mouse.P38$species <- "Mouse"

  objs <- list(obj.opossum, obj.mouse.P38)
  obj.integrated <- IntegrateObjects(objs[[1]], objs[[2]], resolutions = c(1, 2), nfeatures = 3000, subsample = TRUE)
  objs.i <- SplitObject(obj.integrated, split.by = "species")
  objs.m <- MapObjects(objs.i[["Opossum"]], objs.i[["Mouse"]], c("subclass", "type"), assay = "integrated")
  objs.mouse <- append(objs.mouse, objs[[2]])
  objs.opossum <- append(objs.opossum, objs[[1]])
  objs.i.mouse <- append(objs.i.mouse, objs.i[["Mouse"]])
  objs.i.opossum <- append(objs.i.opossum, objs.i[["Opossum"]])
  objs.m.mouse <- append(objs.m.mouse, objs.m[[2]])
  objs.m.opossum <- append(objs.m.opossum, objs.m[[1]])
  
}

obj.mouse <- merge(objs.mouse[[1]], y = c(objs.mouse[[2]], objs.mouse[[3]]))
obj.opossum <- merge(objs.opossum[[1]], y = c(objs.opossum[[2]], objs.opossum[[3]]))
obj.m.mouse <- merge(objs.m.mouse[[1]], y = c(objs.m.mouse[[2]], objs.m.mouse[[3]]))
obj.m.opossum <- merge(objs.m.opossum[[1]], y = c(objs.m.opossum[[2]], objs.m.opossum[[3]]))

obj.mouse <- ClusterSCT(obj.mouse, c(1))
obj.m.mouse <- ClusterSCT(obj.m.mouse, c(1))
obj.opossum <- ClusterSCT(obj.opossum, c(1))
obj.m.opossum <- ClusterSCT(obj.m.opossum, c(1))

obj.mouse <- readRDS("E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/obj_mouse.rds")
Loading required package: SeuratObject
Loading required package: sp
obj.opossum <- readRDS("E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/obj_opossum.rds")
objs.i.mouse <- readRDS("E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/obj_i_mouse.rds")
objs.i.opossum <- readRDS("E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/obj_i_opossum.rds")
objs.m.mouse <- readRDS("E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/objs_m_mouse.rds")
objs.m.opossum <- readRDS("E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/objs_m_opossum.rds")
obj.m.mouse <- readRDS("E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/obj_m_mouse.rds")
obj.m.opossum <- readRDS("E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/obj_m_opossum.rds")

colors_list <- list(
              # Glutamatergic
              IT = "#FF6C88",
              IT_A = "#FFB3B3",
              `L2/3` = "#FFB3B3",
              IT_B = "#FFA07A",
              L4 = "#FF7F50",
              IT_C = "#FF7F50",
              L5IT = "#FFA07A",
              IT_D = "#FF6347",
              L6IT = "#FF6347",
              L5NP = "#FF4500",
              L5PT = "#FF8C69",
              L6CT = "#FFA07A",
              L6b = "#FF6347",
            
              # GABAergic
              Pvalb = "#1E90FF",
              Sst = "#87CEEB",
              Vip = "#87CEFA",
              Lamp5 = "#4682B4",
              Frem1 = "#ADD8E6",
              Stac = "#5F9EA0",
            
              # Non-neuronal
              Astro = "#8C8C8C",
              Micro = "#A0A0A0",
              OD = "#B4B4B4",
              OPC = "#C8C8C8",
              Endo = "#505050",
              VLMC = "#B4B4B4"
)

obj.mouse$species <- "Mouse"
obj.opossum$species <- "Opossum"
obj.combined <- merge(obj.mouse, y = obj.opossum)
obj.combined$subclass.plot <- obj.combined$subclass
obj.combined$subclass.plot[obj.combined$subclass %in% c("IT_A", "IT_B", "IT_C", "IT_D", "IT_E", 
                                                   "L2/3", "L4", "L5IT", "L6IT")] <- "IT"

Idents(obj.combined) <- "subclass.plot"
levels(obj.combined) <- rev(c("IT", "L5NP", "L5PT", "L6CT", "L6b",
                              "Pvalb", "Sst", "Vip", "Lamp5", "Frem1", "Stac", 
                              "Astro", "Micro", "OD", "OPC", "Endo", "VLMC"))
DotPlot(obj.combined, assay = "RNA", features = c("Snap25", "Sv2b", "Cux2", "Rorb", "Deptor", "Etv1", "Trpc4", "Foxp2", "Lin28b", 
                                                  "Gad1", "Myo5b", "Sst", "Vip", "Lamp5", "Frem1", "Stac", 
                                                  "Aldh1l1", "Cx3cr1", "Mog", "Pdgfra", "Flt1", "Slc47a1"), cols = c("#a6a6a6", "#c692b8"), split.by = "species", scale = TRUE) + theme(axis.text.x=element_text(angle = 90, vjust = 0.4))


obj.opossum$subclass.plot <- obj.opossum$subclass
obj.opossum$subclass.plot[obj.opossum$subclass %in% c("IT_A", "IT_B", "IT_C", "IT_D", "IT_E", 
                                                        "L2/3", "L4", "L5IT", "L6IT")] <- "IT"
opossum.counts <- as.data.frame.matrix(table(obj.opossum$sample, obj.opossum$subclass.plot))
opossum.counts$Stac <- 0
opossum.counts$VLMC <- 0
opossum.counts$species <- "Opossum"
opossum.counts$Glutamatergic <- rowSums(opossum.counts[, c("IT", "L5NP", "L5PT", "L6CT", "L6b")])
opossum.counts$GABAergic <- rowSums(opossum.counts[, c("Pvalb", "Sst", "Vip", "Lamp5", "Frem1", "Stac")])
opossum.counts$Nonneuronal <- rowSums(opossum.counts[, c("Astro", "Micro", "OD", "OPC", "Endo", "VLMC")])

obj.mouse$subclass.plot <- obj.mouse$subclass
obj.mouse$subclass.plot[obj.mouse$subclass %in% c("IT_A", "IT_B", "IT_C", "IT_D", "IT_E", 
                                                        "L2/3", "L4", "L5IT", "L6IT")] <- "IT"
mouse.counts <- as.data.frame.matrix(table(obj.mouse$sample, obj.mouse$subclass.plot))
mouse.counts$species <- "Mouse"
mouse.counts$Glutamatergic <- rowSums(mouse.counts[, c("IT", "L5NP", "L5PT", "L6CT", "L6b")])
mouse.counts$GABAergic <- rowSums(mouse.counts[, c("Pvalb", "Sst", "Vip", "Lamp5", "Frem1", "Stac")])
mouse.counts$Nonneuronal <- rowSums(mouse.counts[, c("Astro", "Micro", "OD", "OPC", "Endo", "VLMC")])

all.counts <- rbind(opossum.counts, mouse.counts)

all.props <- all.counts %>%
  mutate(IT = IT / Glutamatergic,
         L5NP = L5NP / Glutamatergic,
         L5PT = L5PT / Glutamatergic,
         L6CT = L6CT / Glutamatergic,
         L6b = L6b / Glutamatergic,
         Pvalb = Pvalb / GABAergic,
         Sst = Sst / GABAergic,
         Vip = Vip / GABAergic,
         Lamp5 = Lamp5 / GABAergic,
         Frem1 = Frem1 / GABAergic, 
         Stac = Stac / GABAergic, 
         Astro = Astro / Nonneuronal,
         Micro = Micro / Nonneuronal,
         OD = OD / Nonneuronal,
         OPC = OPC / Nonneuronal,
         Endo = Endo / Nonneuronal
         )

scatter.props <- all.props

all.props.long <- all.props %>%
                  pivot_longer(
                    cols = c("IT", "L5NP", "L5PT", "L6CT", "L6b", 
                             "Pvalb", "Sst", "Vip", "Lamp5", "Frem1", "Stac", 
                             "Astro", "Micro", "OD", "OPC", "Endo", "VLMC", 
                             "Glutamatergic", "GABAergic", "Nonneuronal"),
                    names_to = "cell.identity", 
                    values_to = "fraction"
                               )

all.props.long$species <- factor(all.props.long$species, levels = c("Opossum", "Mouse"))

curr.props <- all.props.long[all.props.long$cell.identity %in% c("IT", "L5NP", "L5PT", "L6CT", "L6b"), ]

ggplot(curr.props, aes(x = factor(cell.identity, level = c("IT", "L5NP", "L5PT", "L6CT", "L6b")), y = fraction, fill = species)) +
    geom_bar(stat = "summary", fun = "median", position = position_dodge(width = 0.8), width = 0.75) +
    geom_point(colour = "black", position = position_dodge(width = 0.8), size = 1) +
    scale_x_discrete(labels = c("IT", "L5NP", "L5PT", "L6CT", "L6b")) +
    scale_y_continuous(breaks = c(0, 0.2, 0.4, 0.6, 0.8), expand = c(0, 0), limits = c(0, 0.80)) +
    guides(fill = guide_legend(override.aes = list(shape = NA))) +
    theme_classic() + theme(axis.text = element_text(color = "black"), legend.text = element_text(size = 10)) + 
    labs(x = NULL, y = "Fraction of Glutamatergic Cells", fill = NULL) + 
    scale_fill_manual("legend", values = c("Opossum" = "#c692b8", "Mouse" = "#aaaaaa"))


all.props.long$species <- factor(all.props.long$species, levels = c("Opossum", "Mouse"))

curr.props <- all.props.long[all.props.long$cell.identity %in% c("Pvalb", "Sst", "Vip", "Lamp5", "Frem1", "Stac"), ]

ggplot(curr.props, aes(x = factor(cell.identity, level = c("Pvalb", "Sst", "Vip", "Lamp5", "Frem1", "Stac")), y = fraction, fill = species)) +
    geom_bar(stat = "summary", fun = "median", position = position_dodge(width = 0.8), width = 0.75) +
    geom_point(colour = "black", position = position_dodge(width = 0.8), size = 1) +
    scale_x_discrete(labels = c("Pvalb", "Sst", "Vip", "Lamp5", "Frem1", "Stac")) +
    scale_y_continuous(breaks = c(0, 0.2, 0.4, 0.6), expand = c(0, 0), limits = c(0, 0.60)) +
    guides(fill = guide_legend(override.aes = list(shape = NA))) +
    theme_classic() + theme(axis.text = element_text(color = "black"), legend.text = element_text(size = 10)) + 
    labs(x = NULL, y = "Fraction of GABAergic Cells", fill = NULL) + 
    scale_fill_manual("legend", values = c("Opossum" = "#c692b8", "Mouse" = "#aaaaaa"))


all.props.long$species <- factor(all.props.long$species, levels = c("Opossum", "Mouse"))

curr.props <- all.props.long[all.props.long$cell.identity %in% c("Astro", "Micro", "OD", "OPC", "Endo", "VLMC"), ]

ggplot(curr.props, aes(x = factor(cell.identity, level = c("Astro", "Micro", "OD", "OPC", "Endo", "VLMC")), y = fraction, fill = species)) +
    geom_bar(stat = "summary", fun = "median", position = position_dodge(width = 0.8), width = 0.75) +
    geom_point(colour = "black", position = position_dodge(width = 0.8), size = 1) +
    scale_x_discrete(labels = c("Astro", "Micro", "OD", "OPC", "Endo", "VLMC")) +
    scale_y_continuous(breaks = c(0, 0.2, 0.4, 0.6, 0.8), expand = c(0, 0), limits = c(0, 0.60)) +
    guides(fill = guide_legend(override.aes = list(shape = NA))) +
    theme_classic() + theme(axis.text = element_text(color = "black"), legend.text = element_text(size = 10)) + 
    labs(x = NULL, y = "Fraction of Nonneuronal Cells", fill = NULL) + 
    scale_fill_manual("legend", values = c("Opossum" = "#c692b8", "Mouse" = "#aaaaaa"))


opossum.counts <- as.data.frame.matrix(table(obj.opossum.IT$sample, obj.opossum.IT$subclass))
opossum.counts$`L2/3` <- opossum.counts$IT_A
opossum.counts$L4 <- opossum.counts$IT_C
opossum.counts$L5IT <- opossum.counts$IT_B
opossum.counts$L6IT <- opossum.counts$IT_D
opossum.counts$species <- "Opossum"
opossum.counts$Glutamatergic <- rowSums(opossum.counts[, c("L2/3", "L4", "L5IT", "L6IT", "L5NP", "L5PT", "L6CT", "L6b")])

mouse.counts <- as.data.frame.matrix(table(obj.mouse.IT$sample, obj.mouse.IT$subclass))
mouse.counts$IT_A <- mouse.counts$`L2/3`
mouse.counts$IT_C <- mouse.counts$L4
mouse.counts$IT_B <- mouse.counts$L5IT
mouse.counts$IT_D <- mouse.counts$L6IT
mouse.counts$species <- "Mouse"
mouse.counts$Glutamatergic <- rowSums(mouse.counts[, c("L2/3", "L4", "L5IT", "L6IT", "L5NP", "L5PT", "L6CT", "L6b")])

all.counts <- rbind(opossum.counts, mouse.counts)

all.props <- all.counts %>%
  mutate(`L2/3` = `L2/3` / Glutamatergic,
         L4 = L4 / Glutamatergic,
         L5IT = L5IT / Glutamatergic,
         L6IT = L6IT / Glutamatergic,
         L5NP = L5NP / Glutamatergic,
         L5PT = L5PT / Glutamatergic,
         L6CT = L6CT / Glutamatergic,
         L6b = L6b / Glutamatergic
         )

scatter.props <- all.props

all.props.long <- all.props %>%
                  pivot_longer(
                    cols = c("L2/3", "L4", "L5IT", "L6IT", "L5NP", "L5PT", "L6CT", "L6b"),
                    names_to = "cell.identity", 
                    values_to = "fraction"
                               )

all.props.long$species <- factor(all.props.long$species, levels = c("Opossum", "Mouse"))

curr.props <- all.props.long[all.props.long$cell.identity %in% c("L2/3", "L4", "L5IT", "L6IT", "L5NP", "L5PT", "L6CT", "L6b"), ]

ggplot(curr.props, aes(x = factor(cell.identity, level = c("L2/3", "L4", "L5IT", "L6IT", "L5NP", "L5PT", "L6CT", "L6b")), y = fraction, fill = species)) +
    geom_bar(stat = "summary", fun = "median", position = position_dodge(width = 0.8), width = 0.75) +
    geom_point(colour = "black", position = position_dodge(width = 0.8), size = 1) +
    scale_x_discrete(labels = c("L2/3", "L4", "L5IT", "L6IT", "L5NP", "L5PT", "L6CT", "L6b")) +
    scale_y_continuous(breaks = c(0, 0.2, 0.4, 0.6), expand = c(0, 0), limits = c(0, 0.60)) +
    guides(fill = guide_legend(override.aes = list(shape = NA))) +
    theme_classic() + theme(axis.text = element_text(color = "black"), legend.text = element_text(size = 10)) + 
    labs(x = NULL, y = "Fraction of Glutamatergic Cells", fill = NULL) + 
    scale_fill_manual("legend", values = c("Opossum" = "#c692b8", "Mouse" = "#aaaaaa"))


DimPlot(obj.mouse, reduction = "umap", group.by = "sample", label = FALSE, raster = FALSE, shuffle = TRUE) + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
DimPlot(obj.mouse, reduction = "umap", group.by = "subclass", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
DimPlot(obj.mouse, reduction = "umap", group.by = "type", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()

obj.mouse$subclass.IT <- obj.mouse$subclass
obj.mouse$subclass.IT[obj.mouse$subclass %in% c("L2/3", "L4", "L5IT", "L6IT")] <-  "IT"
p <- DimPlot(obj.mouse, reduction = "umap", group.by = "subclass", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
ggsave("E:/Opossum_Paper/Figure 1/Mouse-P38_V1_All_UMAP_Subclass_FullSpace.png", plot = p, dpi = 300)
ggsave("E:/Opossum_Paper/Figure 1/Mouse-P38_V1_All_UMAP_Subclass_FullSpace.svg", plot = p, dpi = 300)
p <- DimPlot(obj.mouse, reduction = "umap", group.by = "subclass.IT", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
ggsave("E:/Opossum_Paper/Figure 1/Mouse-P38_V1_All_UMAP_SubclassIT_FullSpace.png", plot = p, dpi = 300)
ggsave("E:/Opossum_Paper/Figure 1/Mouse-P38_V1_All_UMAP_SubclassIT_FullSpace.svg", plot = p, dpi = 300)

obj.opossum$subclass.plot <- obj.opossum$subclass
obj.opossum$subclass.plot[obj.opossum$subclass %in% c("IT_A", "IT_B", "IT_C", "IT_D", "IT_E", 
                                                      "L2/3", "L4", "L5IT", "L6IT")] <- "IT"

opossum.subclass.plot.levels <- c("IT", "L5NP", "L5PT", "L6CT", "L6b", 
                                  "Pvalb", "Sst", "Vip", "Lamp5", "Frem1", 
                                  "Astro", "Micro", "OD", "OPC", "Endo")

opossum.subclass.levels <- c("IT_A", "IT_B", "IT_C", "IT_D", "IT_E", "L5NP", "L5PT", "L6CT", "L6b", 
                                  "Pvalb", "Sst", "Vip", "Lamp5", "Frem1", 
                                  "Astro", "Micro", "OD", "OPC", "Endo")

Idents(obj.opossum) <- "subclass.plot"
levels(obj.opossum) <- opossum.subclass.plot.levels
colors <- as.character(colors_list[opossum.subclass.plot.levels])
DimPlot(obj.opossum, reduction = "umap", label = TRUE, raster = FALSE, shuffle = TRUE, cols = colors) + NoLegend() + xlim(-17, 13) + ylim(-13, 17) + coord_equal()


opossum.subclass.levels <- c("IT_A", "IT_B", "IT_C", "IT_D", "L5NP", "L5PT", "L6CT", "L6b", 
                             "Pvalb", "Sst", "Vip", "Lamp5", "Frem1", 
                             "Astro", "Micro", "OD", "OPC", "Endo")

Idents(obj.m.opossum) <- "subclass"
levels(obj.m.opossum) <- opossum.subclass.levels
colors <- as.character(colors_list[opossum.subclass.levels])
DimPlot(obj.m.opossum, reduction = "umap", label = TRUE, raster = FALSE, shuffle = TRUE, cols = colors) + NoLegend() + xlim(-16, 13) + ylim(-12, 17) + coord_equal()


mouse.subclass.levels <- c("L2/3", "L4", "L6IT", "L5PT", "L6CT", "L6b", 
                           "Pvalb", "Sst", "Vip", "Lamp5", "Frem1", "Stac",
                           "Astro", "Micro", "OD", "OPC", "Endo")

Idents(obj.m.opossum) <- "predicted.subclass"
levels(obj.m.opossum) <- mouse.subclass.levels
colors <- as.character(colors_list[mouse.subclass.levels])
DimPlot(obj.m.opossum, reduction = "umap", label = TRUE, raster = FALSE, shuffle = TRUE, cols = colors) + NoLegend() + xlim(-16, 13) + ylim(-12, 17) + coord_equal()


obj.mouse$subclass.plot <- obj.mouse$subclass
obj.mouse$subclass.plot[obj.mouse$subclass %in% c("IT_A", "IT_B", "IT_C", "IT_D", "IT_E", 
                                                      "L2/3", "L4", "L5IT", "L6IT")] <- "IT"

mouse.subclass.plot.levels <- c("IT", "L5NP", "L5PT", "L6CT", "L6b", 
                                "Pvalb", "Sst", "Vip", "Lamp5", "Frem1", "Stac",
                                "Astro", "Micro", "OD", "OPC", "Endo", "VLMC")

mouse.subclass.levels <- c("L2/3", "L4", "L5IT", "L6IT", "L5NP", "L5PT", "L6CT", "L6b", 
                           "Pvalb", "Sst", "Vip", "Lamp5", "Frem1", "Stac",
                           "Astro", "Micro", "OD", "OPC", "Endo", "VLMC")

Idents(obj.mouse) <- "subclass.plot"
levels(obj.mouse) <- mouse.subclass.plot.levels
colors <- as.character(colors_list[mouse.subclass.plot.levels])
DimPlot(obj.mouse, reduction = "umap", label = TRUE, raster = FALSE, shuffle = TRUE, cols = colors) + NoLegend() + xlim(-16, 16) + ylim(-17, 15) + coord_equal()


mouse.subclass.levels <- c("L2/3", "L4", "L5IT", "L6IT", "L5NP", "L5PT", "L6CT", "L6b", 
                           "Pvalb", "Sst", "Vip", "Lamp5", "Frem1", "Stac", 
                           "Astro", "Micro", "OD", "OPC", "Endo", "VLMC")

Idents(obj.m.mouse) <- "subclass"
levels(obj.m.mouse) <- mouse.subclass.levels
colors <- as.character(colors_list[mouse.subclass.levels])
DimPlot(obj.m.mouse, reduction = "umap", label = TRUE, raster = FALSE, shuffle = TRUE, cols = colors) + NoLegend() + xlim(-14, 18) + ylim(-16, 16) + coord_equal()


DimPlot(obj.m.mouse, reduction = "umap", group.by = "sample", label = FALSE, raster = FALSE, shuffle = TRUE) + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
DimPlot(obj.m.mouse, reduction = "umap", group.by = "subclass", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
DimPlot(obj.m.mouse, reduction = "umap", group.by = "predicted.subclass", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
DimPlot(obj.m.mouse, reduction = "umap", group.by = "type", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()

p <- DimPlot(obj.m.mouse, reduction = "umap", group.by = "subclass", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
ggsave("E:/Opossum_Paper/Figure 1/Mouse-P38_V1_All_UMAP_Subclass_IntSpace.svg", plot = p, dpi = 300)
ggsave("E:/Opossum_Paper/Figure 1/Mouse-P38_V1_All_UMAP_Subclass_IntSpace.png", plot = p, dpi = 300)
p <- DimPlot(obj.m.mouse, reduction = "umap", group.by = "predicted.subclass", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
ggsave("E:/Opossum_Paper/Figure 1/Mouse-P38_V1_All_UMAP_PredictedSubclass_IntSpace.svg", plot = p, dpi = 300)
ggsave("E:/Opossum_Paper/Figure 1/Mouse-P38_V1_All_UMAP_PredictedSubclass_IntSpace.png", plot = p, dpi = 300)

DimPlot(obj.opossum, reduction = "umap", group.by = "sample", label = FALSE, raster = FALSE, shuffle = TRUE) + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
DimPlot(obj.opossum, reduction = "umap", group.by = "subclass", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
DimPlot(obj.opossum, reduction = "umap", group.by = "type", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()

obj.opossum$subclass.IT <- obj.opossum$subclass
obj.opossum$subclass.IT[obj.opossum$subclass %in% c("IT_A", "IT_B", "IT_C", "IT_D", "IT_E")] <-  "IT"
p <- DimPlot(obj.opossum, reduction = "umap", group.by = "subclass", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
ggsave("E:/Opossum_Paper/Figure 1/Opossum_V1_All_UMAP_Subclass_FullSpace.png", plot = p, dpi = 300)
ggsave("E:/Opossum_Paper/Figure 1/Opossum_V1_All_UMAP_Subclass_FullSpace.svg", plot = p, dpi = 300)
p <- DimPlot(obj.opossum, reduction = "umap", group.by = "subclass.IT", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
ggsave("E:/Opossum_Paper/Figure 1/Opossum_V1_All_UMAP_SubclassIT_FullSpace.png", plot = p, dpi = 300)
ggsave("E:/Opossum_Paper/Figure 1/Opossum_V1_All_UMAP_SubclassIT_FullSpace.svg", plot = p, dpi = 300)

DimPlot(obj.m.opossum, reduction = "umap", group.by = "sample", label = FALSE, raster = FALSE, shuffle = TRUE) + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
DimPlot(obj.m.opossum, reduction = "umap", group.by = "subclass", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
DimPlot(obj.m.opossum, reduction = "umap", group.by = "predicted.subclass", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
DimPlot(obj.m.opossum, reduction = "umap", group.by = "type", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()

p <- DimPlot(obj.m.opossum, reduction = "umap", group.by = "subclass", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
ggsave("E:/Opossum_Paper/Figure 1/Opossum_V1_All_UMAP_Subclass_IntSpace.svg", plot = p, dpi = 300)
ggsave("E:/Opossum_Paper/Figure 1/Opossum_V1_All_UMAP_Subclass_IntSpace.png", plot = p, dpi = 300)
p <- DimPlot(obj.m.opossum, reduction = "umap", group.by = "predicted.subclass", label = TRUE, raster = FALSE, shuffle = TRUE) + NoLegend() + xlim(-18, 18) + ylim(-18, 18) + coord_equal()
ggsave("E:/Opossum_Paper/Figure 1/Opossum_V1_All_UMAP_PredictedSubclass_IntSpace.svg", plot = p, dpi = 300)
ggsave("E:/Opossum_Paper/Figure 1/Opossum_V1_All_UMAP_PredictedSubclass_IntSpace.png", plot = p, dpi = 300)

PlotMapping(list(objs.m.mouse[[1]], objs.m.opossum[[1]]), ident.order = c("IT_A", "IT_B", "IT_C", "IT_D", "L2/3", "L4", "L5IT", "L6IT", "L5NP", "L5PT", "L6CT", "L6b"))


PlotMapping(list(objs.m.mouse[[2]], objs.m.opossum[[2]]), ident.order = c("Pvalb", "Sst", "Vip", "Lamp5", "Frem1", "Stac"))


PlotMapping(list(objs.m.mouse[[3]], objs.m.opossum[[3]]), ident.order = c("Astro", "Micro", "OD", "OPC", "Endo", "VLMC"))


opossum.glutamatergic.levels <- c("IT_A", "IT_B", "IT_C", "IT_D", "L5NP", "L5PT", "L6CT", "L6b")
Idents(objs.m.opossum[[1]]) <- "subclass"
levels(objs.m.opossum[[1]]) <- opossum.glutamatergic.levels
VlnPlot(objs.m.opossum[[1]], "predicted.subclass.score", cols = colors_list[opossum.glutamatergic.levels]) + theme(legend.spacing.x = unit(3.0, 'cm'))


opossum.gabaergic.levels <- c("Pvalb", "Sst", "Vip", "Lamp5", "Frem1")
Idents(objs.m.opossum[[2]]) <- "subclass"
levels(objs.m.opossum[[2]]) <- opossum.gabaergic.levels
VlnPlot(objs.m.opossum[[2]], "predicted.subclass.score", cols = colors_list[opossum.gabaergic.levels]) + theme(legend.spacing.x = unit(6.5, 'cm'))


opossum.nonneuronal.levels <- c("Astro", "Micro", "OD", "OPC", "Endo")
Idents(objs.m.opossum[[3]]) <- "subclass"
levels(objs.m.opossum[[3]]) <- opossum.nonneuronal.levels
VlnPlot(objs.m.opossum[[3]], "predicted.subclass.score", cols = colors_list[opossum.nonneuronal.levels]) + theme(legend.spacing.x = unit(6.5, 'cm'))


saveRDS(obj.mouse, "E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/obj_mouse.rds")
saveRDS(obj.opossum, "E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/obj_opossum.rds")
saveRDS(objs.i.mouse, "E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/obj_i_mouse.rds")
saveRDS(objs.i.opossum, "E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/obj_i_opossum.rds")
saveRDS(objs.m.mouse, "E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/objs_m_mouse.rds")
saveRDS(objs.m.opossum, "E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/objs_m_opossum.rds")
saveRDS(obj.m.mouse, "E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/obj_m_mouse.rds")
saveRDS(obj.m.opossum, "E:/Transcriptomics_V1/Integration/Opossum_Mouse-P38/obj_m_opossum.rds")
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KFNldXJhdCkNCmxpYnJhcnkoU2V1cmF0RGlzaykNCmxpYnJhcnkocmV0aWN1bGF0ZSkNCmxpYnJhcnkoc2NydWJsZXRSKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShwYXRjaHdvcmspDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShjbHVzdHJlZSkNCmxpYnJhcnkocmVzaGFwZTIpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeShncmlkRXh0cmEpDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KHBseXIpDQpzb3VyY2UoIkM6L1J5YW4vR2l0SHViL3RyYWNodGVuYmVyZy1sYWIvdHJhbnNjcmlwdG9taWNzL3Rvb2xzL3NldXJhdF9mdW5jdGlvbnMuUiIpDQpzb3VyY2UoIkM6L1J5YW4vR2l0SHViL3RyYWNodGVuYmVyZy1sYWIvdHJhbnNjcmlwdG9taWNzL3Rvb2xzL3NldXJhdF9pbnRlZ3JhdGlvbl9mdW5jdGlvbnMuUiIpDQpzb3VyY2UoIkM6L1J5YW4vR2l0SHViL3RyYWNodGVuYmVyZy1sYWIvdHJhbnNjcmlwdG9taWNzL3hnYm9vc3QveGdib29zdF90cmFpbi5SIikNCnNvdXJjZSgiQzovUnlhbi9HaXRIdWIvdHJhY2h0ZW5iZXJnLWxhYi90cmFuc2NyaXB0b21pY3MveGdib29zdC9wbG90dGluZ0Z4bnMuUiIpDQoNCmNsYXNzZXMgPC0gYygiR2x1dGFtYXRlcmdpYyIsICJHQUJBZXJnaWMiLCAiTm9ubmV1cm9uYWwiKQ0Kb2Jqcy5tb3VzZSA8LSBjKCkNCm9ianMub3Bvc3N1bSA8LSBjKCkNCm9ianMuaS5tb3VzZSA8LSBjKCkNCm9ianMuaS5vcG9zc3VtIDwtIGMoKQ0Kb2Jqcy5tLm1vdXNlIDwtIGMoKQ0Kb2Jqcy5tLm9wb3NzdW0gPC0gYygpDQoNCmZvciAoY2wgaW4gY2xhc3Nlcykgew0KDQogIG9iai5vcG9zc3VtIDwtIHJlYWRSRFMocGFzdGUwKCJFOi9UcmFuc2NyaXB0b21pY3NfVjEvT3Bvc3N1bS9zZXVyYXQvb3Bvc3N1bV92MV8iLCB0b2xvd2VyKGNsKSwgIl9wcm9jZXNzZWQucmRzIikpDQogIG9iai5vcG9zc3VtJHNwZWNpZXMgPC0gIk9wb3NzdW0iDQogIG9iai5tb3VzZS5QMzggPC0gcmVhZFJEUyhwYXN0ZTAoIkU6L1RyYW5zY3JpcHRvbWljc19WMS9Nb3VzZS9zZXVyYXQvbW91c2VfdjFfUDM4XyIsIHRvbG93ZXIoY2wpLCAiX3Byb2Nlc3NlZC5yZHMiKSkNCiAgb2JqLm1vdXNlLlAzOCRzcGVjaWVzIDwtICJNb3VzZSINCg0KICBvYmpzIDwtIGxpc3Qob2JqLm9wb3NzdW0sIG9iai5tb3VzZS5QMzgpDQogIG9iai5pbnRlZ3JhdGVkIDwtIEludGVncmF0ZU9iamVjdHMob2Jqc1tbMV1dLCBvYmpzW1syXV0sIHJlc29sdXRpb25zID0gYygxLCAyKSwgbmZlYXR1cmVzID0gMzAwMCwgc3Vic2FtcGxlID0gVFJVRSkNCiAgb2Jqcy5pIDwtIFNwbGl0T2JqZWN0KG9iai5pbnRlZ3JhdGVkLCBzcGxpdC5ieSA9ICJzcGVjaWVzIikNCiAgb2Jqcy5tIDwtIE1hcE9iamVjdHMob2Jqcy5pW1siT3Bvc3N1bSJdXSwgb2Jqcy5pW1siTW91c2UiXV0sIGMoInN1YmNsYXNzIiwgInR5cGUiKSwgYXNzYXkgPSAiaW50ZWdyYXRlZCIpDQogIG9ianMubW91c2UgPC0gYXBwZW5kKG9ianMubW91c2UsIG9ianNbWzJdXSkNCiAgb2Jqcy5vcG9zc3VtIDwtIGFwcGVuZChvYmpzLm9wb3NzdW0sIG9ianNbWzFdXSkNCiAgb2Jqcy5pLm1vdXNlIDwtIGFwcGVuZChvYmpzLmkubW91c2UsIG9ianMuaVtbIk1vdXNlIl1dKQ0KICBvYmpzLmkub3Bvc3N1bSA8LSBhcHBlbmQob2Jqcy5pLm9wb3NzdW0sIG9ianMuaVtbIk9wb3NzdW0iXV0pDQogIG9ianMubS5tb3VzZSA8LSBhcHBlbmQob2Jqcy5tLm1vdXNlLCBvYmpzLm1bWzJdXSkNCiAgb2Jqcy5tLm9wb3NzdW0gPC0gYXBwZW5kKG9ianMubS5vcG9zc3VtLCBvYmpzLm1bWzFdXSkNCiAgDQp9DQoNCm9iai5tb3VzZSA8LSBtZXJnZShvYmpzLm1vdXNlW1sxXV0sIHkgPSBjKG9ianMubW91c2VbWzJdXSwgb2Jqcy5tb3VzZVtbM11dKSkNCm9iai5vcG9zc3VtIDwtIG1lcmdlKG9ianMub3Bvc3N1bVtbMV1dLCB5ID0gYyhvYmpzLm9wb3NzdW1bWzJdXSwgb2Jqcy5vcG9zc3VtW1szXV0pKQ0Kb2JqLm0ubW91c2UgPC0gbWVyZ2Uob2Jqcy5tLm1vdXNlW1sxXV0sIHkgPSBjKG9ianMubS5tb3VzZVtbMl1dLCBvYmpzLm0ubW91c2VbWzNdXSkpDQpvYmoubS5vcG9zc3VtIDwtIG1lcmdlKG9ianMubS5vcG9zc3VtW1sxXV0sIHkgPSBjKG9ianMubS5vcG9zc3VtW1syXV0sIG9ianMubS5vcG9zc3VtW1szXV0pKQ0KDQpgYGANCg0KDQpgYGB7cn0NCg0Kb2JqLm1vdXNlIDwtIENsdXN0ZXJTQ1Qob2JqLm1vdXNlLCBjKDEpKQ0Kb2JqLm0ubW91c2UgPC0gQ2x1c3RlclNDVChvYmoubS5tb3VzZSwgYygxKSkNCm9iai5vcG9zc3VtIDwtIENsdXN0ZXJTQ1Qob2JqLm9wb3NzdW0sIGMoMSkpDQpvYmoubS5vcG9zc3VtIDwtIENsdXN0ZXJTQ1Qob2JqLm0ub3Bvc3N1bSwgYygxKSkNCg0KYGBgDQoNCg0KYGBge3J9DQoNCm9iai5tb3VzZSA8LSByZWFkUkRTKCJFOi9UcmFuc2NyaXB0b21pY3NfVjEvSW50ZWdyYXRpb24vT3Bvc3N1bV9Nb3VzZS1QMzgvb2JqX21vdXNlLnJkcyIpDQpvYmoub3Bvc3N1bSA8LSByZWFkUkRTKCJFOi9UcmFuc2NyaXB0b21pY3NfVjEvSW50ZWdyYXRpb24vT3Bvc3N1bV9Nb3VzZS1QMzgvb2JqX29wb3NzdW0ucmRzIikNCm9ianMuaS5tb3VzZSA8LSByZWFkUkRTKCJFOi9UcmFuc2NyaXB0b21pY3NfVjEvSW50ZWdyYXRpb24vT3Bvc3N1bV9Nb3VzZS1QMzgvb2JqX2lfbW91c2UucmRzIikNCm9ianMuaS5vcG9zc3VtIDwtIHJlYWRSRFMoIkU6L1RyYW5zY3JpcHRvbWljc19WMS9JbnRlZ3JhdGlvbi9PcG9zc3VtX01vdXNlLVAzOC9vYmpfaV9vcG9zc3VtLnJkcyIpDQpvYmpzLm0ubW91c2UgPC0gcmVhZFJEUygiRTovVHJhbnNjcmlwdG9taWNzX1YxL0ludGVncmF0aW9uL09wb3NzdW1fTW91c2UtUDM4L29ianNfbV9tb3VzZS5yZHMiKQ0Kb2Jqcy5tLm9wb3NzdW0gPC0gcmVhZFJEUygiRTovVHJhbnNjcmlwdG9taWNzX1YxL0ludGVncmF0aW9uL09wb3NzdW1fTW91c2UtUDM4L29ianNfbV9vcG9zc3VtLnJkcyIpDQpvYmoubS5tb3VzZSA8LSByZWFkUkRTKCJFOi9UcmFuc2NyaXB0b21pY3NfVjEvSW50ZWdyYXRpb24vT3Bvc3N1bV9Nb3VzZS1QMzgvb2JqX21fbW91c2UucmRzIikNCm9iai5tLm9wb3NzdW0gPC0gcmVhZFJEUygiRTovVHJhbnNjcmlwdG9taWNzX1YxL0ludGVncmF0aW9uL09wb3NzdW1fTW91c2UtUDM4L29ial9tX29wb3NzdW0ucmRzIikNCg0KYGBgDQoNCg0KYGBge3J9DQoNCmNvbG9yc19saXN0IDwtIGxpc3QoDQogICAgICAgICAgICAgICMgR2x1dGFtYXRlcmdpYw0KICAgICAgICAgICAgICBJVCA9ICIjRkY2Qzg4IiwNCiAgICAgICAgICAgICAgSVRfQSA9ICIjRkZCM0IzIiwNCiAgICAgICAgICAgICAgYEwyLzNgID0gIiNGRkIzQjMiLA0KICAgICAgICAgICAgICBJVF9CID0gIiNGRkEwN0EiLA0KICAgICAgICAgICAgICBMNCA9ICIjRkY3RjUwIiwNCiAgICAgICAgICAgICAgSVRfQyA9ICIjRkY3RjUwIiwNCiAgICAgICAgICAgICAgTDVJVCA9ICIjRkZBMDdBIiwNCiAgICAgICAgICAgICAgSVRfRCA9ICIjRkY2MzQ3IiwNCiAgICAgICAgICAgICAgTDZJVCA9ICIjRkY2MzQ3IiwNCiAgICAgICAgICAgICAgTDVOUCA9ICIjRkY0NTAwIiwNCiAgICAgICAgICAgICAgTDVQVCA9ICIjRkY4QzY5IiwNCiAgICAgICAgICAgICAgTDZDVCA9ICIjRkZBMDdBIiwNCiAgICAgICAgICAgICAgTDZiID0gIiNGRjYzNDciLA0KICAgICAgICAgICAgDQogICAgICAgICAgICAgICMgR0FCQWVyZ2ljDQogICAgICAgICAgICAgIFB2YWxiID0gIiMxRTkwRkYiLA0KICAgICAgICAgICAgICBTc3QgPSAiIzg3Q0VFQiIsDQogICAgICAgICAgICAgIFZpcCA9ICIjODdDRUZBIiwNCiAgICAgICAgICAgICAgTGFtcDUgPSAiIzQ2ODJCNCIsDQogICAgICAgICAgICAgIEZyZW0xID0gIiNBREQ4RTYiLA0KICAgICAgICAgICAgICBTdGFjID0gIiM1RjlFQTAiLA0KICAgICAgICAgICAgDQogICAgICAgICAgICAgICMgTm9uLW5ldXJvbmFsDQogICAgICAgICAgICAgIEFzdHJvID0gIiM4QzhDOEMiLA0KICAgICAgICAgICAgICBNaWNybyA9ICIjQTBBMEEwIiwNCiAgICAgICAgICAgICAgT0QgPSAiI0I0QjRCNCIsDQogICAgICAgICAgICAgIE9QQyA9ICIjQzhDOEM4IiwNCiAgICAgICAgICAgICAgRW5kbyA9ICIjNTA1MDUwIiwNCiAgICAgICAgICAgICAgVkxNQyA9ICIjQjRCNEI0Ig0KKQ0KDQpgYGANCg0KDQpgYGB7cn0NCg0Kb2JqLm1vdXNlJHNwZWNpZXMgPC0gIk1vdXNlIg0Kb2JqLm9wb3NzdW0kc3BlY2llcyA8LSAiT3Bvc3N1bSINCm9iai5jb21iaW5lZCA8LSBtZXJnZShvYmoubW91c2UsIHkgPSBvYmoub3Bvc3N1bSkNCm9iai5jb21iaW5lZCRzdWJjbGFzcy5wbG90IDwtIG9iai5jb21iaW5lZCRzdWJjbGFzcw0Kb2JqLmNvbWJpbmVkJHN1YmNsYXNzLnBsb3Rbb2JqLmNvbWJpbmVkJHN1YmNsYXNzICVpbiUgYygiSVRfQSIsICJJVF9CIiwgIklUX0MiLCAiSVRfRCIsICJJVF9FIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMMi8zIiwgIkw0IiwgIkw1SVQiLCAiTDZJVCIpXSA8LSAiSVQiDQoNCmBgYA0KDQoNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9OH0NCg0KSWRlbnRzKG9iai5jb21iaW5lZCkgPC0gInN1YmNsYXNzLnBsb3QiDQpsZXZlbHMob2JqLmNvbWJpbmVkKSA8LSByZXYoYygiSVQiLCAiTDVOUCIsICJMNVBUIiwgIkw2Q1QiLCAiTDZiIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQdmFsYiIsICJTc3QiLCAiVmlwIiwgIkxhbXA1IiwgIkZyZW0xIiwgIlN0YWMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBc3RybyIsICJNaWNybyIsICJPRCIsICJPUEMiLCAiRW5kbyIsICJWTE1DIikpDQpEb3RQbG90KG9iai5jb21iaW5lZCwgYXNzYXkgPSAiUk5BIiwgZmVhdHVyZXMgPSBjKCJTbmFwMjUiLCAiU3YyYiIsICJDdXgyIiwgIlJvcmIiLCAiRGVwdG9yIiwgIkV0djEiLCAiVHJwYzQiLCAiRm94cDIiLCAiTGluMjhiIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHYWQxIiwgIk15bzViIiwgIlNzdCIsICJWaXAiLCAiTGFtcDUiLCAiRnJlbTEiLCAiU3RhYyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQWxkaDFsMSIsICJDeDNjcjEiLCAiTW9nIiwgIlBkZ2ZyYSIsICJGbHQxIiwgIlNsYzQ3YTEiKSwgY29scyA9IGMoIiNhNmE2YTYiLCAiI2M2OTJiOCIpLCBzcGxpdC5ieSA9ICJzcGVjaWVzIiwgc2NhbGUgPSBUUlVFKSArIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNCkpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQpvYmoub3Bvc3N1bSRzdWJjbGFzcy5wbG90IDwtIG9iai5vcG9zc3VtJHN1YmNsYXNzDQpvYmoub3Bvc3N1bSRzdWJjbGFzcy5wbG90W29iai5vcG9zc3VtJHN1YmNsYXNzICVpbiUgYygiSVRfQSIsICJJVF9CIiwgIklUX0MiLCAiSVRfRCIsICJJVF9FIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMMi8zIiwgIkw0IiwgIkw1SVQiLCAiTDZJVCIpXSA8LSAiSVQiDQpvcG9zc3VtLmNvdW50cyA8LSBhcy5kYXRhLmZyYW1lLm1hdHJpeCh0YWJsZShvYmoub3Bvc3N1bSRzYW1wbGUsIG9iai5vcG9zc3VtJHN1YmNsYXNzLnBsb3QpKQ0Kb3Bvc3N1bS5jb3VudHMkU3RhYyA8LSAwDQpvcG9zc3VtLmNvdW50cyRWTE1DIDwtIDANCm9wb3NzdW0uY291bnRzJHNwZWNpZXMgPC0gIk9wb3NzdW0iDQpvcG9zc3VtLmNvdW50cyRHbHV0YW1hdGVyZ2ljIDwtIHJvd1N1bXMob3Bvc3N1bS5jb3VudHNbLCBjKCJJVCIsICJMNU5QIiwgIkw1UFQiLCAiTDZDVCIsICJMNmIiKV0pDQpvcG9zc3VtLmNvdW50cyRHQUJBZXJnaWMgPC0gcm93U3VtcyhvcG9zc3VtLmNvdW50c1ssIGMoIlB2YWxiIiwgIlNzdCIsICJWaXAiLCAiTGFtcDUiLCAiRnJlbTEiLCAiU3RhYyIpXSkNCm9wb3NzdW0uY291bnRzJE5vbm5ldXJvbmFsIDwtIHJvd1N1bXMob3Bvc3N1bS5jb3VudHNbLCBjKCJBc3RybyIsICJNaWNybyIsICJPRCIsICJPUEMiLCAiRW5kbyIsICJWTE1DIildKQ0KDQpvYmoubW91c2Ukc3ViY2xhc3MucGxvdCA8LSBvYmoubW91c2Ukc3ViY2xhc3MNCm9iai5tb3VzZSRzdWJjbGFzcy5wbG90W29iai5tb3VzZSRzdWJjbGFzcyAlaW4lIGMoIklUX0EiLCAiSVRfQiIsICJJVF9DIiwgIklUX0QiLCAiSVRfRSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTDIvMyIsICJMNCIsICJMNUlUIiwgIkw2SVQiKV0gPC0gIklUIg0KbW91c2UuY291bnRzIDwtIGFzLmRhdGEuZnJhbWUubWF0cml4KHRhYmxlKG9iai5tb3VzZSRzYW1wbGUsIG9iai5tb3VzZSRzdWJjbGFzcy5wbG90KSkNCm1vdXNlLmNvdW50cyRzcGVjaWVzIDwtICJNb3VzZSINCm1vdXNlLmNvdW50cyRHbHV0YW1hdGVyZ2ljIDwtIHJvd1N1bXMobW91c2UuY291bnRzWywgYygiSVQiLCAiTDVOUCIsICJMNVBUIiwgIkw2Q1QiLCAiTDZiIildKQ0KbW91c2UuY291bnRzJEdBQkFlcmdpYyA8LSByb3dTdW1zKG1vdXNlLmNvdW50c1ssIGMoIlB2YWxiIiwgIlNzdCIsICJWaXAiLCAiTGFtcDUiLCAiRnJlbTEiLCAiU3RhYyIpXSkNCm1vdXNlLmNvdW50cyROb25uZXVyb25hbCA8LSByb3dTdW1zKG1vdXNlLmNvdW50c1ssIGMoIkFzdHJvIiwgIk1pY3JvIiwgIk9EIiwgIk9QQyIsICJFbmRvIiwgIlZMTUMiKV0pDQoNCmFsbC5jb3VudHMgPC0gcmJpbmQob3Bvc3N1bS5jb3VudHMsIG1vdXNlLmNvdW50cykNCg0KYWxsLnByb3BzIDwtIGFsbC5jb3VudHMgJT4lDQogIG11dGF0ZShJVCA9IElUIC8gR2x1dGFtYXRlcmdpYywNCiAgICAgICAgIEw1TlAgPSBMNU5QIC8gR2x1dGFtYXRlcmdpYywNCiAgICAgICAgIEw1UFQgPSBMNVBUIC8gR2x1dGFtYXRlcmdpYywNCiAgICAgICAgIEw2Q1QgPSBMNkNUIC8gR2x1dGFtYXRlcmdpYywNCiAgICAgICAgIEw2YiA9IEw2YiAvIEdsdXRhbWF0ZXJnaWMsDQogICAgICAgICBQdmFsYiA9IFB2YWxiIC8gR0FCQWVyZ2ljLA0KICAgICAgICAgU3N0ID0gU3N0IC8gR0FCQWVyZ2ljLA0KICAgICAgICAgVmlwID0gVmlwIC8gR0FCQWVyZ2ljLA0KICAgICAgICAgTGFtcDUgPSBMYW1wNSAvIEdBQkFlcmdpYywNCiAgICAgICAgIEZyZW0xID0gRnJlbTEgLyBHQUJBZXJnaWMsIA0KICAgICAgICAgU3RhYyA9IFN0YWMgLyBHQUJBZXJnaWMsIA0KICAgICAgICAgQXN0cm8gPSBBc3RybyAvIE5vbm5ldXJvbmFsLA0KICAgICAgICAgTWljcm8gPSBNaWNybyAvIE5vbm5ldXJvbmFsLA0KICAgICAgICAgT0QgPSBPRCAvIE5vbm5ldXJvbmFsLA0KICAgICAgICAgT1BDID0gT1BDIC8gTm9ubmV1cm9uYWwsDQogICAgICAgICBFbmRvID0gRW5kbyAvIE5vbm5ldXJvbmFsDQogICAgICAgICApDQoNCnNjYXR0ZXIucHJvcHMgPC0gYWxsLnByb3BzDQoNCmFsbC5wcm9wcy5sb25nIDwtIGFsbC5wcm9wcyAlPiUNCiAgICAgICAgICAgICAgICAgIHBpdm90X2xvbmdlcigNCiAgICAgICAgICAgICAgICAgICAgY29scyA9IGMoIklUIiwgIkw1TlAiLCAiTDVQVCIsICJMNkNUIiwgIkw2YiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUHZhbGIiLCAiU3N0IiwgIlZpcCIsICJMYW1wNSIsICJGcmVtMSIsICJTdGFjIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBc3RybyIsICJNaWNybyIsICJPRCIsICJPUEMiLCAiRW5kbyIsICJWTE1DIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHbHV0YW1hdGVyZ2ljIiwgIkdBQkFlcmdpYyIsICJOb25uZXVyb25hbCIpLA0KICAgICAgICAgICAgICAgICAgICBuYW1lc190byA9ICJjZWxsLmlkZW50aXR5IiwgDQogICAgICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJmcmFjdGlvbiINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQoNCmBgYA0KDQoNCmBgYHtyLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD00fQ0KDQphbGwucHJvcHMubG9uZyRzcGVjaWVzIDwtIGZhY3RvcihhbGwucHJvcHMubG9uZyRzcGVjaWVzLCBsZXZlbHMgPSBjKCJPcG9zc3VtIiwgIk1vdXNlIikpDQoNCmN1cnIucHJvcHMgPC0gYWxsLnByb3BzLmxvbmdbYWxsLnByb3BzLmxvbmckY2VsbC5pZGVudGl0eSAlaW4lIGMoIklUIiwgIkw1TlAiLCAiTDVQVCIsICJMNkNUIiwgIkw2YiIpLCBdDQoNCmdncGxvdChjdXJyLnByb3BzLCBhZXMoeCA9IGZhY3RvcihjZWxsLmlkZW50aXR5LCBsZXZlbCA9IGMoIklUIiwgIkw1TlAiLCAiTDVQVCIsICJMNkNUIiwgIkw2YiIpKSwgeSA9IGZyYWN0aW9uLCBmaWxsID0gc3BlY2llcykpICsNCiAgICBnZW9tX2JhcihzdGF0ID0gInN1bW1hcnkiLCBmdW4gPSAibWVkaWFuIiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksIHdpZHRoID0gMC43NSkgKw0KICAgIGdlb21fcG9pbnQoY29sb3VyID0gImJsYWNrIiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksIHNpemUgPSAxKSArDQogICAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBjKCJJVCIsICJMNU5QIiwgIkw1UFQiLCAiTDZDVCIsICJMNmIiKSkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBjKDAsIDAuMiwgMC40LCAwLjYsIDAuOCksIGV4cGFuZCA9IGMoMCwgMCksIGxpbWl0cyA9IGMoMCwgMC44MCkpICsNCiAgICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNoYXBlID0gTkEpKSkgKw0KICAgIHRoZW1lX2NsYXNzaWMoKSArIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArIA0KICAgIGxhYnMoeCA9IE5VTEwsIHkgPSAiRnJhY3Rpb24gb2YgR2x1dGFtYXRlcmdpYyBDZWxscyIsIGZpbGwgPSBOVUxMKSArIA0KICAgIHNjYWxlX2ZpbGxfbWFudWFsKCJsZWdlbmQiLCB2YWx1ZXMgPSBjKCJPcG9zc3VtIiA9ICIjYzY5MmI4IiwgIk1vdXNlIiA9ICIjYWFhYWFhIikpDQoNCmBgYA0KDQoNCmBgYHtyLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD00LjV9DQoNCmFsbC5wcm9wcy5sb25nJHNwZWNpZXMgPC0gZmFjdG9yKGFsbC5wcm9wcy5sb25nJHNwZWNpZXMsIGxldmVscyA9IGMoIk9wb3NzdW0iLCAiTW91c2UiKSkNCg0KY3Vyci5wcm9wcyA8LSBhbGwucHJvcHMubG9uZ1thbGwucHJvcHMubG9uZyRjZWxsLmlkZW50aXR5ICVpbiUgYygiUHZhbGIiLCAiU3N0IiwgIlZpcCIsICJMYW1wNSIsICJGcmVtMSIsICJTdGFjIiksIF0NCg0KZ2dwbG90KGN1cnIucHJvcHMsIGFlcyh4ID0gZmFjdG9yKGNlbGwuaWRlbnRpdHksIGxldmVsID0gYygiUHZhbGIiLCAiU3N0IiwgIlZpcCIsICJMYW1wNSIsICJGcmVtMSIsICJTdGFjIikpLCB5ID0gZnJhY3Rpb24sIGZpbGwgPSBzcGVjaWVzKSkgKw0KICAgIGdlb21fYmFyKHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWRpYW4iLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC44KSwgd2lkdGggPSAwLjc1KSArDQogICAgZ2VvbV9wb2ludChjb2xvdXIgPSAiYmxhY2siLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC44KSwgc2l6ZSA9IDEpICsNCiAgICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoIlB2YWxiIiwgIlNzdCIsICJWaXAiLCAiTGFtcDUiLCAiRnJlbTEiLCAiU3RhYyIpKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoMCwgMC4yLCAwLjQsIDAuNiksIGV4cGFuZCA9IGMoMCwgMCksIGxpbWl0cyA9IGMoMCwgMC42MCkpICsNCiAgICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNoYXBlID0gTkEpKSkgKw0KICAgIHRoZW1lX2NsYXNzaWMoKSArIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKSArIA0KICAgIGxhYnMoeCA9IE5VTEwsIHkgPSAiRnJhY3Rpb24gb2YgR0FCQWVyZ2ljIENlbGxzIiwgZmlsbCA9IE5VTEwpICsgDQogICAgc2NhbGVfZmlsbF9tYW51YWwoImxlZ2VuZCIsIHZhbHVlcyA9IGMoIk9wb3NzdW0iID0gIiNjNjkyYjgiLCAiTW91c2UiID0gIiNhYWFhYWEiKSkNCg0KYGBgDQoNCg0KYGBge3IsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTQuNX0NCg0KYWxsLnByb3BzLmxvbmckc3BlY2llcyA8LSBmYWN0b3IoYWxsLnByb3BzLmxvbmckc3BlY2llcywgbGV2ZWxzID0gYygiT3Bvc3N1bSIsICJNb3VzZSIpKQ0KDQpjdXJyLnByb3BzIDwtIGFsbC5wcm9wcy5sb25nW2FsbC5wcm9wcy5sb25nJGNlbGwuaWRlbnRpdHkgJWluJSBjKCJBc3RybyIsICJNaWNybyIsICJPRCIsICJPUEMiLCAiRW5kbyIsICJWTE1DIiksIF0NCg0KZ2dwbG90KGN1cnIucHJvcHMsIGFlcyh4ID0gZmFjdG9yKGNlbGwuaWRlbnRpdHksIGxldmVsID0gYygiQXN0cm8iLCAiTWljcm8iLCAiT0QiLCAiT1BDIiwgIkVuZG8iLCAiVkxNQyIpKSwgeSA9IGZyYWN0aW9uLCBmaWxsID0gc3BlY2llcykpICsNCiAgICBnZW9tX2JhcihzdGF0ID0gInN1bW1hcnkiLCBmdW4gPSAibWVkaWFuIiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksIHdpZHRoID0gMC43NSkgKw0KICAgIGdlb21fcG9pbnQoY29sb3VyID0gImJsYWNrIiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksIHNpemUgPSAxKSArDQogICAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBjKCJBc3RybyIsICJNaWNybyIsICJPRCIsICJPUEMiLCAiRW5kbyIsICJWTE1DIikpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygwLCAwLjIsIDAuNCwgMC42LCAwLjgpLCBleHBhbmQgPSBjKDAsIDApLCBsaW1pdHMgPSBjKDAsIDAuNjApKSArDQogICAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaGFwZSA9IE5BKSkpICsNCiAgICB0aGVtZV9jbGFzc2ljKCkgKyB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkgKyANCiAgICBsYWJzKHggPSBOVUxMLCB5ID0gIkZyYWN0aW9uIG9mIE5vbm5ldXJvbmFsIENlbGxzIiwgZmlsbCA9IE5VTEwpICsgDQogICAgc2NhbGVfZmlsbF9tYW51YWwoImxlZ2VuZCIsIHZhbHVlcyA9IGMoIk9wb3NzdW0iID0gIiNjNjkyYjgiLCAiTW91c2UiID0gIiNhYWFhYWEiKSkNCg0KYGBgDQoNCg0KYGBge3J9DQoNCm9wb3NzdW0uY291bnRzIDwtIGFzLmRhdGEuZnJhbWUubWF0cml4KHRhYmxlKG9iai5vcG9zc3VtLklUJHNhbXBsZSwgb2JqLm9wb3NzdW0uSVQkc3ViY2xhc3MpKQ0Kb3Bvc3N1bS5jb3VudHMkYEwyLzNgIDwtIG9wb3NzdW0uY291bnRzJElUX0ENCm9wb3NzdW0uY291bnRzJEw0IDwtIG9wb3NzdW0uY291bnRzJElUX0MNCm9wb3NzdW0uY291bnRzJEw1SVQgPC0gb3Bvc3N1bS5jb3VudHMkSVRfQg0Kb3Bvc3N1bS5jb3VudHMkTDZJVCA8LSBvcG9zc3VtLmNvdW50cyRJVF9EDQpvcG9zc3VtLmNvdW50cyRzcGVjaWVzIDwtICJPcG9zc3VtIg0Kb3Bvc3N1bS5jb3VudHMkR2x1dGFtYXRlcmdpYyA8LSByb3dTdW1zKG9wb3NzdW0uY291bnRzWywgYygiTDIvMyIsICJMNCIsICJMNUlUIiwgIkw2SVQiLCAiTDVOUCIsICJMNVBUIiwgIkw2Q1QiLCAiTDZiIildKQ0KDQptb3VzZS5jb3VudHMgPC0gYXMuZGF0YS5mcmFtZS5tYXRyaXgodGFibGUob2JqLm1vdXNlLklUJHNhbXBsZSwgb2JqLm1vdXNlLklUJHN1YmNsYXNzKSkNCm1vdXNlLmNvdW50cyRJVF9BIDwtIG1vdXNlLmNvdW50cyRgTDIvM2ANCm1vdXNlLmNvdW50cyRJVF9DIDwtIG1vdXNlLmNvdW50cyRMNA0KbW91c2UuY291bnRzJElUX0IgPC0gbW91c2UuY291bnRzJEw1SVQNCm1vdXNlLmNvdW50cyRJVF9EIDwtIG1vdXNlLmNvdW50cyRMNklUDQptb3VzZS5jb3VudHMkc3BlY2llcyA8LSAiTW91c2UiDQptb3VzZS5jb3VudHMkR2x1dGFtYXRlcmdpYyA8LSByb3dTdW1zKG1vdXNlLmNvdW50c1ssIGMoIkwyLzMiLCAiTDQiLCAiTDVJVCIsICJMNklUIiwgIkw1TlAiLCAiTDVQVCIsICJMNkNUIiwgIkw2YiIpXSkNCg0KYWxsLmNvdW50cyA8LSByYmluZChvcG9zc3VtLmNvdW50cywgbW91c2UuY291bnRzKQ0KDQphbGwucHJvcHMgPC0gYWxsLmNvdW50cyAlPiUNCiAgbXV0YXRlKGBMMi8zYCA9IGBMMi8zYCAvIEdsdXRhbWF0ZXJnaWMsDQogICAgICAgICBMNCA9IEw0IC8gR2x1dGFtYXRlcmdpYywNCiAgICAgICAgIEw1SVQgPSBMNUlUIC8gR2x1dGFtYXRlcmdpYywNCiAgICAgICAgIEw2SVQgPSBMNklUIC8gR2x1dGFtYXRlcmdpYywNCiAgICAgICAgIEw1TlAgPSBMNU5QIC8gR2x1dGFtYXRlcmdpYywNCiAgICAgICAgIEw1UFQgPSBMNVBUIC8gR2x1dGFtYXRlcmdpYywNCiAgICAgICAgIEw2Q1QgPSBMNkNUIC8gR2x1dGFtYXRlcmdpYywNCiAgICAgICAgIEw2YiA9IEw2YiAvIEdsdXRhbWF0ZXJnaWMNCiAgICAgICAgICkNCg0Kc2NhdHRlci5wcm9wcyA8LSBhbGwucHJvcHMNCg0KYWxsLnByb3BzLmxvbmcgPC0gYWxsLnByb3BzICU+JQ0KICAgICAgICAgICAgICAgICAgcGl2b3RfbG9uZ2VyKA0KICAgICAgICAgICAgICAgICAgICBjb2xzID0gYygiTDIvMyIsICJMNCIsICJMNUlUIiwgIkw2SVQiLCAiTDVOUCIsICJMNVBUIiwgIkw2Q1QiLCAiTDZiIiksDQogICAgICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gImNlbGwuaWRlbnRpdHkiLCANCiAgICAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gImZyYWN0aW9uIg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkNCg0KYGBgDQoNCg0KYGBge3IsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTQuNX0NCg0KYWxsLnByb3BzLmxvbmckc3BlY2llcyA8LSBmYWN0b3IoYWxsLnByb3BzLmxvbmckc3BlY2llcywgbGV2ZWxzID0gYygiT3Bvc3N1bSIsICJNb3VzZSIpKQ0KDQpjdXJyLnByb3BzIDwtIGFsbC5wcm9wcy5sb25nW2FsbC5wcm9wcy5sb25nJGNlbGwuaWRlbnRpdHkgJWluJSBjKCJMMi8zIiwgIkw0IiwgIkw1SVQiLCAiTDZJVCIsICJMNU5QIiwgIkw1UFQiLCAiTDZDVCIsICJMNmIiKSwgXQ0KDQpnZ3Bsb3QoY3Vyci5wcm9wcywgYWVzKHggPSBmYWN0b3IoY2VsbC5pZGVudGl0eSwgbGV2ZWwgPSBjKCJMMi8zIiwgIkw0IiwgIkw1SVQiLCAiTDZJVCIsICJMNU5QIiwgIkw1UFQiLCAiTDZDVCIsICJMNmIiKSksIHkgPSBmcmFjdGlvbiwgZmlsbCA9IHNwZWNpZXMpKSArDQogICAgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gIm1lZGlhbiIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjgpLCB3aWR0aCA9IDAuNzUpICsNCiAgICBnZW9tX3BvaW50KGNvbG91ciA9ICJibGFjayIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjgpLCBzaXplID0gMSkgKw0KICAgIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygiTDIvMyIsICJMNCIsICJMNUlUIiwgIkw2SVQiLCAiTDVOUCIsICJMNVBUIiwgIkw2Q1QiLCAiTDZiIikpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygwLCAwLjIsIDAuNCwgMC42KSwgZXhwYW5kID0gYygwLCAwKSwgbGltaXRzID0gYygwLCAwLjYwKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2hhcGUgPSBOQSkpKSArDQogICAgdGhlbWVfY2xhc3NpYygpICsgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsgDQogICAgbGFicyh4ID0gTlVMTCwgeSA9ICJGcmFjdGlvbiBvZiBHbHV0YW1hdGVyZ2ljIENlbGxzIiwgZmlsbCA9IE5VTEwpICsgDQogICAgc2NhbGVfZmlsbF9tYW51YWwoImxlZ2VuZCIsIHZhbHVlcyA9IGMoIk9wb3NzdW0iID0gIiNjNjkyYjgiLCAiTW91c2UiID0gIiNhYWFhYWEiKSkNCg0KYGBgDQoNCg0KYGBge3J9DQoNCkRpbVBsb3Qob2JqLm1vdXNlLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInNhbXBsZSIsIGxhYmVsID0gRkFMU0UsIHJhc3RlciA9IEZBTFNFLCBzaHVmZmxlID0gVFJVRSkgKyB4bGltKC0xOCwgMTgpICsgeWxpbSgtMTgsIDE4KSArIGNvb3JkX2VxdWFsKCkNCkRpbVBsb3Qob2JqLm1vdXNlLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInN1YmNsYXNzIiwgbGFiZWwgPSBUUlVFLCByYXN0ZXIgPSBGQUxTRSwgc2h1ZmZsZSA9IFRSVUUpICsgTm9MZWdlbmQoKSArIHhsaW0oLTE4LCAxOCkgKyB5bGltKC0xOCwgMTgpICsgY29vcmRfZXF1YWwoKQ0KRGltUGxvdChvYmoubW91c2UsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAidHlwZSIsIGxhYmVsID0gVFJVRSwgcmFzdGVyID0gRkFMU0UsIHNodWZmbGUgPSBUUlVFKSArIE5vTGVnZW5kKCkgKyB4bGltKC0xOCwgMTgpICsgeWxpbSgtMTgsIDE4KSArIGNvb3JkX2VxdWFsKCkNCg0Kb2JqLm1vdXNlJHN1YmNsYXNzLklUIDwtIG9iai5tb3VzZSRzdWJjbGFzcw0Kb2JqLm1vdXNlJHN1YmNsYXNzLklUW29iai5tb3VzZSRzdWJjbGFzcyAlaW4lIGMoIkwyLzMiLCAiTDQiLCAiTDVJVCIsICJMNklUIildIDwtICAiSVQiDQpwIDwtIERpbVBsb3Qob2JqLm1vdXNlLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInN1YmNsYXNzIiwgbGFiZWwgPSBUUlVFLCByYXN0ZXIgPSBGQUxTRSwgc2h1ZmZsZSA9IFRSVUUpICsgTm9MZWdlbmQoKSArIHhsaW0oLTE4LCAxOCkgKyB5bGltKC0xOCwgMTgpICsgY29vcmRfZXF1YWwoKQ0KZ2dzYXZlKCJFOi9PcG9zc3VtX1BhcGVyL0ZpZ3VyZSAxL01vdXNlLVAzOF9WMV9BbGxfVU1BUF9TdWJjbGFzc19GdWxsU3BhY2UucG5nIiwgcGxvdCA9IHAsIGRwaSA9IDMwMCkNCmdnc2F2ZSgiRTovT3Bvc3N1bV9QYXBlci9GaWd1cmUgMS9Nb3VzZS1QMzhfVjFfQWxsX1VNQVBfU3ViY2xhc3NfRnVsbFNwYWNlLnN2ZyIsIHBsb3QgPSBwLCBkcGkgPSAzMDApDQpwIDwtIERpbVBsb3Qob2JqLm1vdXNlLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInN1YmNsYXNzLklUIiwgbGFiZWwgPSBUUlVFLCByYXN0ZXIgPSBGQUxTRSwgc2h1ZmZsZSA9IFRSVUUpICsgTm9MZWdlbmQoKSArIHhsaW0oLTE4LCAxOCkgKyB5bGltKC0xOCwgMTgpICsgY29vcmRfZXF1YWwoKQ0KZ2dzYXZlKCJFOi9PcG9zc3VtX1BhcGVyL0ZpZ3VyZSAxL01vdXNlLVAzOF9WMV9BbGxfVU1BUF9TdWJjbGFzc0lUX0Z1bGxTcGFjZS5wbmciLCBwbG90ID0gcCwgZHBpID0gMzAwKQ0KZ2dzYXZlKCJFOi9PcG9zc3VtX1BhcGVyL0ZpZ3VyZSAxL01vdXNlLVAzOF9WMV9BbGxfVU1BUF9TdWJjbGFzc0lUX0Z1bGxTcGFjZS5zdmciLCBwbG90ID0gcCwgZHBpID0gMzAwKQ0KDQpgYGANCg0KDQpgYGB7cn0NCg0Kb2JqLm9wb3NzdW0kc3ViY2xhc3MucGxvdCA8LSBvYmoub3Bvc3N1bSRzdWJjbGFzcw0Kb2JqLm9wb3NzdW0kc3ViY2xhc3MucGxvdFtvYmoub3Bvc3N1bSRzdWJjbGFzcyAlaW4lIGMoIklUX0EiLCAiSVRfQiIsICJJVF9DIiwgIklUX0QiLCAiSVRfRSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkwyLzMiLCAiTDQiLCAiTDVJVCIsICJMNklUIildIDwtICJJVCINCg0Kb3Bvc3N1bS5zdWJjbGFzcy5wbG90LmxldmVscyA8LSBjKCJJVCIsICJMNU5QIiwgIkw1UFQiLCAiTDZDVCIsICJMNmIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUHZhbGIiLCAiU3N0IiwgIlZpcCIsICJMYW1wNSIsICJGcmVtMSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBc3RybyIsICJNaWNybyIsICJPRCIsICJPUEMiLCAiRW5kbyIpDQoNCm9wb3NzdW0uc3ViY2xhc3MubGV2ZWxzIDwtIGMoIklUX0EiLCAiSVRfQiIsICJJVF9DIiwgIklUX0QiLCAiSVRfRSIsICJMNU5QIiwgIkw1UFQiLCAiTDZDVCIsICJMNmIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUHZhbGIiLCAiU3N0IiwgIlZpcCIsICJMYW1wNSIsICJGcmVtMSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBc3RybyIsICJNaWNybyIsICJPRCIsICJPUEMiLCAiRW5kbyIpDQoNCklkZW50cyhvYmoub3Bvc3N1bSkgPC0gInN1YmNsYXNzLnBsb3QiDQpsZXZlbHMob2JqLm9wb3NzdW0pIDwtIG9wb3NzdW0uc3ViY2xhc3MucGxvdC5sZXZlbHMNCmNvbG9ycyA8LSBhcy5jaGFyYWN0ZXIoY29sb3JzX2xpc3Rbb3Bvc3N1bS5zdWJjbGFzcy5wbG90LmxldmVsc10pDQpEaW1QbG90KG9iai5vcG9zc3VtLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSwgcmFzdGVyID0gRkFMU0UsIHNodWZmbGUgPSBUUlVFLCBjb2xzID0gY29sb3JzKSArIE5vTGVnZW5kKCkgKyB4bGltKC0xNywgMTMpICsgeWxpbSgtMTMsIDE3KSArIGNvb3JkX2VxdWFsKCkNCg0KYGBgDQoNCg0KYGBge3J9DQoNCm9wb3NzdW0uc3ViY2xhc3MubGV2ZWxzIDwtIGMoIklUX0EiLCAiSVRfQiIsICJJVF9DIiwgIklUX0QiLCAiTDVOUCIsICJMNVBUIiwgIkw2Q1QiLCAiTDZiIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQdmFsYiIsICJTc3QiLCAiVmlwIiwgIkxhbXA1IiwgIkZyZW0xIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBc3RybyIsICJNaWNybyIsICJPRCIsICJPUEMiLCAiRW5kbyIpDQoNCklkZW50cyhvYmoubS5vcG9zc3VtKSA8LSAic3ViY2xhc3MiDQpsZXZlbHMob2JqLm0ub3Bvc3N1bSkgPC0gb3Bvc3N1bS5zdWJjbGFzcy5sZXZlbHMNCmNvbG9ycyA8LSBhcy5jaGFyYWN0ZXIoY29sb3JzX2xpc3Rbb3Bvc3N1bS5zdWJjbGFzcy5sZXZlbHNdKQ0KRGltUGxvdChvYmoubS5vcG9zc3VtLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSwgcmFzdGVyID0gRkFMU0UsIHNodWZmbGUgPSBUUlVFLCBjb2xzID0gY29sb3JzKSArIE5vTGVnZW5kKCkgKyB4bGltKC0xNiwgMTMpICsgeWxpbSgtMTIsIDE3KSArIGNvb3JkX2VxdWFsKCkNCg0KYGBgDQoNCg0KYGBge3J9DQoNCm1vdXNlLnN1YmNsYXNzLmxldmVscyA8LSBjKCJMMi8zIiwgIkw0IiwgIkw2SVQiLCAiTDVQVCIsICJMNkNUIiwgIkw2YiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIlB2YWxiIiwgIlNzdCIsICJWaXAiLCAiTGFtcDUiLCAiRnJlbTEiLCAiU3RhYyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAiQXN0cm8iLCAiTWljcm8iLCAiT0QiLCAiT1BDIiwgIkVuZG8iKQ0KDQpJZGVudHMob2JqLm0ub3Bvc3N1bSkgPC0gInByZWRpY3RlZC5zdWJjbGFzcyINCmxldmVscyhvYmoubS5vcG9zc3VtKSA8LSBtb3VzZS5zdWJjbGFzcy5sZXZlbHMNCmNvbG9ycyA8LSBhcy5jaGFyYWN0ZXIoY29sb3JzX2xpc3RbbW91c2Uuc3ViY2xhc3MubGV2ZWxzXSkNCkRpbVBsb3Qob2JqLm0ub3Bvc3N1bSwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFRSVUUsIHJhc3RlciA9IEZBTFNFLCBzaHVmZmxlID0gVFJVRSwgY29scyA9IGNvbG9ycykgKyBOb0xlZ2VuZCgpICsgeGxpbSgtMTYsIDEzKSArIHlsaW0oLTEyLCAxNykgKyBjb29yZF9lcXVhbCgpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQpvYmoubW91c2Ukc3ViY2xhc3MucGxvdCA8LSBvYmoubW91c2Ukc3ViY2xhc3MNCm9iai5tb3VzZSRzdWJjbGFzcy5wbG90W29iai5tb3VzZSRzdWJjbGFzcyAlaW4lIGMoIklUX0EiLCAiSVRfQiIsICJJVF9DIiwgIklUX0QiLCAiSVRfRSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkwyLzMiLCAiTDQiLCAiTDVJVCIsICJMNklUIildIDwtICJJVCINCg0KbW91c2Uuc3ViY2xhc3MucGxvdC5sZXZlbHMgPC0gYygiSVQiLCAiTDVOUCIsICJMNVBUIiwgIkw2Q1QiLCAiTDZiIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQdmFsYiIsICJTc3QiLCAiVmlwIiwgIkxhbXA1IiwgIkZyZW0xIiwgIlN0YWMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQXN0cm8iLCAiTWljcm8iLCAiT0QiLCAiT1BDIiwgIkVuZG8iLCAiVkxNQyIpDQoNCm1vdXNlLnN1YmNsYXNzLmxldmVscyA8LSBjKCJMMi8zIiwgIkw0IiwgIkw1SVQiLCAiTDZJVCIsICJMNU5QIiwgIkw1UFQiLCAiTDZDVCIsICJMNmIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJQdmFsYiIsICJTc3QiLCAiVmlwIiwgIkxhbXA1IiwgIkZyZW0xIiwgIlN0YWMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFzdHJvIiwgIk1pY3JvIiwgIk9EIiwgIk9QQyIsICJFbmRvIiwgIlZMTUMiKQ0KDQpJZGVudHMob2JqLm1vdXNlKSA8LSAic3ViY2xhc3MucGxvdCINCmxldmVscyhvYmoubW91c2UpIDwtIG1vdXNlLnN1YmNsYXNzLnBsb3QubGV2ZWxzDQpjb2xvcnMgPC0gYXMuY2hhcmFjdGVyKGNvbG9yc19saXN0W21vdXNlLnN1YmNsYXNzLnBsb3QubGV2ZWxzXSkNCkRpbVBsb3Qob2JqLm1vdXNlLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSwgcmFzdGVyID0gRkFMU0UsIHNodWZmbGUgPSBUUlVFLCBjb2xzID0gY29sb3JzKSArIE5vTGVnZW5kKCkgKyB4bGltKC0xNiwgMTYpICsgeWxpbSgtMTcsIDE1KSArIGNvb3JkX2VxdWFsKCkNCg0KYGBgDQoNCg0KYGBge3J9DQoNCm1vdXNlLnN1YmNsYXNzLmxldmVscyA8LSBjKCJMMi8zIiwgIkw0IiwgIkw1SVQiLCAiTDZJVCIsICJMNU5QIiwgIkw1UFQiLCAiTDZDVCIsICJMNmIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJQdmFsYiIsICJTc3QiLCAiVmlwIiwgIkxhbXA1IiwgIkZyZW0xIiwgIlN0YWMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJBc3RybyIsICJNaWNybyIsICJPRCIsICJPUEMiLCAiRW5kbyIsICJWTE1DIikNCg0KSWRlbnRzKG9iai5tLm1vdXNlKSA8LSAic3ViY2xhc3MiDQpsZXZlbHMob2JqLm0ubW91c2UpIDwtIG1vdXNlLnN1YmNsYXNzLmxldmVscw0KY29sb3JzIDwtIGFzLmNoYXJhY3Rlcihjb2xvcnNfbGlzdFttb3VzZS5zdWJjbGFzcy5sZXZlbHNdKQ0KRGltUGxvdChvYmoubS5tb3VzZSwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFRSVUUsIHJhc3RlciA9IEZBTFNFLCBzaHVmZmxlID0gVFJVRSwgY29scyA9IGNvbG9ycykgKyBOb0xlZ2VuZCgpICsgeGxpbSgtMTQsIDE4KSArIHlsaW0oLTE2LCAxNikgKyBjb29yZF9lcXVhbCgpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQpEaW1QbG90KG9iai5tLm1vdXNlLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInNhbXBsZSIsIGxhYmVsID0gRkFMU0UsIHJhc3RlciA9IEZBTFNFLCBzaHVmZmxlID0gVFJVRSkgKyB4bGltKC0xOCwgMTgpICsgeWxpbSgtMTgsIDE4KSArIGNvb3JkX2VxdWFsKCkNCkRpbVBsb3Qob2JqLm0ubW91c2UsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAic3ViY2xhc3MiLCBsYWJlbCA9IFRSVUUsIHJhc3RlciA9IEZBTFNFLCBzaHVmZmxlID0gVFJVRSkgKyBOb0xlZ2VuZCgpICsgeGxpbSgtMTgsIDE4KSArIHlsaW0oLTE4LCAxOCkgKyBjb29yZF9lcXVhbCgpDQpEaW1QbG90KG9iai5tLm1vdXNlLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5zdWJjbGFzcyIsIGxhYmVsID0gVFJVRSwgcmFzdGVyID0gRkFMU0UsIHNodWZmbGUgPSBUUlVFKSArIE5vTGVnZW5kKCkgKyB4bGltKC0xOCwgMTgpICsgeWxpbSgtMTgsIDE4KSArIGNvb3JkX2VxdWFsKCkNCkRpbVBsb3Qob2JqLm0ubW91c2UsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAidHlwZSIsIGxhYmVsID0gVFJVRSwgcmFzdGVyID0gRkFMU0UsIHNodWZmbGUgPSBUUlVFKSArIE5vTGVnZW5kKCkgKyB4bGltKC0xOCwgMTgpICsgeWxpbSgtMTgsIDE4KSArIGNvb3JkX2VxdWFsKCkNCg0KcCA8LSBEaW1QbG90KG9iai5tLm1vdXNlLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInN1YmNsYXNzIiwgbGFiZWwgPSBUUlVFLCByYXN0ZXIgPSBGQUxTRSwgc2h1ZmZsZSA9IFRSVUUpICsgTm9MZWdlbmQoKSArIHhsaW0oLTE4LCAxOCkgKyB5bGltKC0xOCwgMTgpICsgY29vcmRfZXF1YWwoKQ0KZ2dzYXZlKCJFOi9PcG9zc3VtX1BhcGVyL0ZpZ3VyZSAxL01vdXNlLVAzOF9WMV9BbGxfVU1BUF9TdWJjbGFzc19JbnRTcGFjZS5zdmciLCBwbG90ID0gcCwgZHBpID0gMzAwKQ0KZ2dzYXZlKCJFOi9PcG9zc3VtX1BhcGVyL0ZpZ3VyZSAxL01vdXNlLVAzOF9WMV9BbGxfVU1BUF9TdWJjbGFzc19JbnRTcGFjZS5wbmciLCBwbG90ID0gcCwgZHBpID0gMzAwKQ0KcCA8LSBEaW1QbG90KG9iai5tLm1vdXNlLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5zdWJjbGFzcyIsIGxhYmVsID0gVFJVRSwgcmFzdGVyID0gRkFMU0UsIHNodWZmbGUgPSBUUlVFKSArIE5vTGVnZW5kKCkgKyB4bGltKC0xOCwgMTgpICsgeWxpbSgtMTgsIDE4KSArIGNvb3JkX2VxdWFsKCkNCmdnc2F2ZSgiRTovT3Bvc3N1bV9QYXBlci9GaWd1cmUgMS9Nb3VzZS1QMzhfVjFfQWxsX1VNQVBfUHJlZGljdGVkU3ViY2xhc3NfSW50U3BhY2Uuc3ZnIiwgcGxvdCA9IHAsIGRwaSA9IDMwMCkNCmdnc2F2ZSgiRTovT3Bvc3N1bV9QYXBlci9GaWd1cmUgMS9Nb3VzZS1QMzhfVjFfQWxsX1VNQVBfUHJlZGljdGVkU3ViY2xhc3NfSW50U3BhY2UucG5nIiwgcGxvdCA9IHAsIGRwaSA9IDMwMCkNCg0KYGBgDQoNCg0KYGBge3J9DQoNCkRpbVBsb3Qob2JqLm9wb3NzdW0sIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAic2FtcGxlIiwgbGFiZWwgPSBGQUxTRSwgcmFzdGVyID0gRkFMU0UsIHNodWZmbGUgPSBUUlVFKSArIHhsaW0oLTE4LCAxOCkgKyB5bGltKC0xOCwgMTgpICsgY29vcmRfZXF1YWwoKQ0KRGltUGxvdChvYmoub3Bvc3N1bSwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJzdWJjbGFzcyIsIGxhYmVsID0gVFJVRSwgcmFzdGVyID0gRkFMU0UsIHNodWZmbGUgPSBUUlVFKSArIE5vTGVnZW5kKCkgKyB4bGltKC0xOCwgMTgpICsgeWxpbSgtMTgsIDE4KSArIGNvb3JkX2VxdWFsKCkNCkRpbVBsb3Qob2JqLm9wb3NzdW0sIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAidHlwZSIsIGxhYmVsID0gVFJVRSwgcmFzdGVyID0gRkFMU0UsIHNodWZmbGUgPSBUUlVFKSArIE5vTGVnZW5kKCkgKyB4bGltKC0xOCwgMTgpICsgeWxpbSgtMTgsIDE4KSArIGNvb3JkX2VxdWFsKCkNCg0Kb2JqLm9wb3NzdW0kc3ViY2xhc3MuSVQgPC0gb2JqLm9wb3NzdW0kc3ViY2xhc3MNCm9iai5vcG9zc3VtJHN1YmNsYXNzLklUW29iai5vcG9zc3VtJHN1YmNsYXNzICVpbiUgYygiSVRfQSIsICJJVF9CIiwgIklUX0MiLCAiSVRfRCIsICJJVF9FIildIDwtICAiSVQiDQpwIDwtIERpbVBsb3Qob2JqLm9wb3NzdW0sIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAic3ViY2xhc3MiLCBsYWJlbCA9IFRSVUUsIHJhc3RlciA9IEZBTFNFLCBzaHVmZmxlID0gVFJVRSkgKyBOb0xlZ2VuZCgpICsgeGxpbSgtMTgsIDE4KSArIHlsaW0oLTE4LCAxOCkgKyBjb29yZF9lcXVhbCgpDQpnZ3NhdmUoIkU6L09wb3NzdW1fUGFwZXIvRmlndXJlIDEvT3Bvc3N1bV9WMV9BbGxfVU1BUF9TdWJjbGFzc19GdWxsU3BhY2UucG5nIiwgcGxvdCA9IHAsIGRwaSA9IDMwMCkNCmdnc2F2ZSgiRTovT3Bvc3N1bV9QYXBlci9GaWd1cmUgMS9PcG9zc3VtX1YxX0FsbF9VTUFQX1N1YmNsYXNzX0Z1bGxTcGFjZS5zdmciLCBwbG90ID0gcCwgZHBpID0gMzAwKQ0KcCA8LSBEaW1QbG90KG9iai5vcG9zc3VtLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInN1YmNsYXNzLklUIiwgbGFiZWwgPSBUUlVFLCByYXN0ZXIgPSBGQUxTRSwgc2h1ZmZsZSA9IFRSVUUpICsgTm9MZWdlbmQoKSArIHhsaW0oLTE4LCAxOCkgKyB5bGltKC0xOCwgMTgpICsgY29vcmRfZXF1YWwoKQ0KZ2dzYXZlKCJFOi9PcG9zc3VtX1BhcGVyL0ZpZ3VyZSAxL09wb3NzdW1fVjFfQWxsX1VNQVBfU3ViY2xhc3NJVF9GdWxsU3BhY2UucG5nIiwgcGxvdCA9IHAsIGRwaSA9IDMwMCkNCmdnc2F2ZSgiRTovT3Bvc3N1bV9QYXBlci9GaWd1cmUgMS9PcG9zc3VtX1YxX0FsbF9VTUFQX1N1YmNsYXNzSVRfRnVsbFNwYWNlLnN2ZyIsIHBsb3QgPSBwLCBkcGkgPSAzMDApDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQpEaW1QbG90KG9iai5tLm9wb3NzdW0sIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAic2FtcGxlIiwgbGFiZWwgPSBGQUxTRSwgcmFzdGVyID0gRkFMU0UsIHNodWZmbGUgPSBUUlVFKSArIHhsaW0oLTE4LCAxOCkgKyB5bGltKC0xOCwgMTgpICsgY29vcmRfZXF1YWwoKQ0KRGltUGxvdChvYmoubS5vcG9zc3VtLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInN1YmNsYXNzIiwgbGFiZWwgPSBUUlVFLCByYXN0ZXIgPSBGQUxTRSwgc2h1ZmZsZSA9IFRSVUUpICsgTm9MZWdlbmQoKSArIHhsaW0oLTE4LCAxOCkgKyB5bGltKC0xOCwgMTgpICsgY29vcmRfZXF1YWwoKQ0KRGltUGxvdChvYmoubS5vcG9zc3VtLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5zdWJjbGFzcyIsIGxhYmVsID0gVFJVRSwgcmFzdGVyID0gRkFMU0UsIHNodWZmbGUgPSBUUlVFKSArIE5vTGVnZW5kKCkgKyB4bGltKC0xOCwgMTgpICsgeWxpbSgtMTgsIDE4KSArIGNvb3JkX2VxdWFsKCkNCkRpbVBsb3Qob2JqLm0ub3Bvc3N1bSwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJ0eXBlIiwgbGFiZWwgPSBUUlVFLCByYXN0ZXIgPSBGQUxTRSwgc2h1ZmZsZSA9IFRSVUUpICsgTm9MZWdlbmQoKSArIHhsaW0oLTE4LCAxOCkgKyB5bGltKC0xOCwgMTgpICsgY29vcmRfZXF1YWwoKQ0KDQpwIDwtIERpbVBsb3Qob2JqLm0ub3Bvc3N1bSwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJzdWJjbGFzcyIsIGxhYmVsID0gVFJVRSwgcmFzdGVyID0gRkFMU0UsIHNodWZmbGUgPSBUUlVFKSArIE5vTGVnZW5kKCkgKyB4bGltKC0xOCwgMTgpICsgeWxpbSgtMTgsIDE4KSArIGNvb3JkX2VxdWFsKCkNCmdnc2F2ZSgiRTovT3Bvc3N1bV9QYXBlci9GaWd1cmUgMS9PcG9zc3VtX1YxX0FsbF9VTUFQX1N1YmNsYXNzX0ludFNwYWNlLnN2ZyIsIHBsb3QgPSBwLCBkcGkgPSAzMDApDQpnZ3NhdmUoIkU6L09wb3NzdW1fUGFwZXIvRmlndXJlIDEvT3Bvc3N1bV9WMV9BbGxfVU1BUF9TdWJjbGFzc19JbnRTcGFjZS5wbmciLCBwbG90ID0gcCwgZHBpID0gMzAwKQ0KcCA8LSBEaW1QbG90KG9iai5tLm9wb3NzdW0sIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAicHJlZGljdGVkLnN1YmNsYXNzIiwgbGFiZWwgPSBUUlVFLCByYXN0ZXIgPSBGQUxTRSwgc2h1ZmZsZSA9IFRSVUUpICsgTm9MZWdlbmQoKSArIHhsaW0oLTE4LCAxOCkgKyB5bGltKC0xOCwgMTgpICsgY29vcmRfZXF1YWwoKQ0KZ2dzYXZlKCJFOi9PcG9zc3VtX1BhcGVyL0ZpZ3VyZSAxL09wb3NzdW1fVjFfQWxsX1VNQVBfUHJlZGljdGVkU3ViY2xhc3NfSW50U3BhY2Uuc3ZnIiwgcGxvdCA9IHAsIGRwaSA9IDMwMCkNCmdnc2F2ZSgiRTovT3Bvc3N1bV9QYXBlci9GaWd1cmUgMS9PcG9zc3VtX1YxX0FsbF9VTUFQX1ByZWRpY3RlZFN1YmNsYXNzX0ludFNwYWNlLnBuZyIsIHBsb3QgPSBwLCBkcGkgPSAzMDApDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQpQbG90TWFwcGluZyhsaXN0KG9ianMubS5tb3VzZVtbMV1dLCBvYmpzLm0ub3Bvc3N1bVtbMV1dKSwgaWRlbnQub3JkZXIgPSBjKCJJVF9BIiwgIklUX0IiLCAiSVRfQyIsICJJVF9EIiwgIkwyLzMiLCAiTDQiLCAiTDVJVCIsICJMNklUIiwgIkw1TlAiLCAiTDVQVCIsICJMNkNUIiwgIkw2YiIpKQ0KDQpgYGANCg0KDQpgYGB7ciwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NX0NCg0KUGxvdE1hcHBpbmcobGlzdChvYmpzLm0ubW91c2VbWzJdXSwgb2Jqcy5tLm9wb3NzdW1bWzJdXSksIGlkZW50Lm9yZGVyID0gYygiUHZhbGIiLCAiU3N0IiwgIlZpcCIsICJMYW1wNSIsICJGcmVtMSIsICJTdGFjIikpDQoNCmBgYA0KDQoNCmBgYHtyLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD01fQ0KDQpQbG90TWFwcGluZyhsaXN0KG9ianMubS5tb3VzZVtbM11dLCBvYmpzLm0ub3Bvc3N1bVtbM11dKSwgaWRlbnQub3JkZXIgPSBjKCJBc3RybyIsICJNaWNybyIsICJPRCIsICJPUEMiLCAiRW5kbyIsICJWTE1DIikpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQpvcG9zc3VtLmdsdXRhbWF0ZXJnaWMubGV2ZWxzIDwtIGMoIklUX0EiLCAiSVRfQiIsICJJVF9DIiwgIklUX0QiLCAiTDVOUCIsICJMNVBUIiwgIkw2Q1QiLCAiTDZiIikNCklkZW50cyhvYmpzLm0ub3Bvc3N1bVtbMV1dKSA8LSAic3ViY2xhc3MiDQpsZXZlbHMob2Jqcy5tLm9wb3NzdW1bWzFdXSkgPC0gb3Bvc3N1bS5nbHV0YW1hdGVyZ2ljLmxldmVscw0KVmxuUGxvdChvYmpzLm0ub3Bvc3N1bVtbMV1dLCAicHJlZGljdGVkLnN1YmNsYXNzLnNjb3JlIiwgY29scyA9IGNvbG9yc19saXN0W29wb3NzdW0uZ2x1dGFtYXRlcmdpYy5sZXZlbHNdKSArIHRoZW1lKGxlZ2VuZC5zcGFjaW5nLnggPSB1bml0KDMuMCwgJ2NtJykpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQpvcG9zc3VtLmdhYmFlcmdpYy5sZXZlbHMgPC0gYygiUHZhbGIiLCAiU3N0IiwgIlZpcCIsICJMYW1wNSIsICJGcmVtMSIpDQpJZGVudHMob2Jqcy5tLm9wb3NzdW1bWzJdXSkgPC0gInN1YmNsYXNzIg0KbGV2ZWxzKG9ianMubS5vcG9zc3VtW1syXV0pIDwtIG9wb3NzdW0uZ2FiYWVyZ2ljLmxldmVscw0KVmxuUGxvdChvYmpzLm0ub3Bvc3N1bVtbMl1dLCAicHJlZGljdGVkLnN1YmNsYXNzLnNjb3JlIiwgY29scyA9IGNvbG9yc19saXN0W29wb3NzdW0uZ2FiYWVyZ2ljLmxldmVsc10pICsgdGhlbWUobGVnZW5kLnNwYWNpbmcueCA9IHVuaXQoNi41LCAnY20nKSkNCg0KYGBgDQoNCg0KYGBge3J9DQoNCm9wb3NzdW0ubm9ubmV1cm9uYWwubGV2ZWxzIDwtIGMoIkFzdHJvIiwgIk1pY3JvIiwgIk9EIiwgIk9QQyIsICJFbmRvIikNCklkZW50cyhvYmpzLm0ub3Bvc3N1bVtbM11dKSA8LSAic3ViY2xhc3MiDQpsZXZlbHMob2Jqcy5tLm9wb3NzdW1bWzNdXSkgPC0gb3Bvc3N1bS5ub25uZXVyb25hbC5sZXZlbHMNClZsblBsb3Qob2Jqcy5tLm9wb3NzdW1bWzNdXSwgInByZWRpY3RlZC5zdWJjbGFzcy5zY29yZSIsIGNvbHMgPSBjb2xvcnNfbGlzdFtvcG9zc3VtLm5vbm5ldXJvbmFsLmxldmVsc10pICsgdGhlbWUobGVnZW5kLnNwYWNpbmcueCA9IHVuaXQoNi41LCAnY20nKSkNCg0KYGBgDQoNCmBgYHtyfQ0KDQpzYXZlUkRTKG9iai5tb3VzZSwgIkU6L1RyYW5zY3JpcHRvbWljc19WMS9JbnRlZ3JhdGlvbi9PcG9zc3VtX01vdXNlLVAzOC9vYmpfbW91c2UucmRzIikNCnNhdmVSRFMob2JqLm9wb3NzdW0sICJFOi9UcmFuc2NyaXB0b21pY3NfVjEvSW50ZWdyYXRpb24vT3Bvc3N1bV9Nb3VzZS1QMzgvb2JqX29wb3NzdW0ucmRzIikNCnNhdmVSRFMob2Jqcy5pLm1vdXNlLCAiRTovVHJhbnNjcmlwdG9taWNzX1YxL0ludGVncmF0aW9uL09wb3NzdW1fTW91c2UtUDM4L29ial9pX21vdXNlLnJkcyIpDQpzYXZlUkRTKG9ianMuaS5vcG9zc3VtLCAiRTovVHJhbnNjcmlwdG9taWNzX1YxL0ludGVncmF0aW9uL09wb3NzdW1fTW91c2UtUDM4L29ial9pX29wb3NzdW0ucmRzIikNCnNhdmVSRFMob2Jqcy5tLm1vdXNlLCAiRTovVHJhbnNjcmlwdG9taWNzX1YxL0ludGVncmF0aW9uL09wb3NzdW1fTW91c2UtUDM4L29ianNfbV9tb3VzZS5yZHMiKQ0Kc2F2ZVJEUyhvYmpzLm0ub3Bvc3N1bSwgIkU6L1RyYW5zY3JpcHRvbWljc19WMS9JbnRlZ3JhdGlvbi9PcG9zc3VtX01vdXNlLVAzOC9vYmpzX21fb3Bvc3N1bS5yZHMiKQ0Kc2F2ZVJEUyhvYmoubS5tb3VzZSwgIkU6L1RyYW5zY3JpcHRvbWljc19WMS9JbnRlZ3JhdGlvbi9PcG9zc3VtX01vdXNlLVAzOC9vYmpfbV9tb3VzZS5yZHMiKQ0Kc2F2ZVJEUyhvYmoubS5vcG9zc3VtLCAiRTovVHJhbnNjcmlwdG9taWNzX1YxL0ludGVncmF0aW9uL09wb3NzdW1fTW91c2UtUDM4L29ial9tX29wb3NzdW0ucmRzIikNCg0KYGBgDQoNCg==